﻿/************************************************************************

   Extended Silverlight Toolkit

   Copyright (C) 2010-2012 Xceed Software Inc.

   This program is provided to you under the terms of the Microsoft Public
   License (Ms-PL) as published at http://extendedsilverlight.codeplex.com/license

   Please purchase a commercial version of this toolkit if you are using
   it in a commercial product. The commercial versions support the project,
   and also include more features for each control, priority support,
   source code, updates, removed watermark, and a proprietary license.

   Visit http://xceed.com and follow @datagrid on Twitter.

  **********************************************************************/

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Xceed.Silverlight.Data.Stats;

namespace Xceed.Silverlight.Data
{
  internal class SyncDebugLogEnumerator<T> : SyncParentEnumerator<T>
  {
    public SyncDebugLogEnumerator( ISyncEnumerator<T> childEnumerator )
      : this( childEnumerator, ( s ) => System.Diagnostics.Debug.WriteLine( s ) )
    {
    }

    public SyncDebugLogEnumerator( ISyncEnumerator<T> childEnumerator, Action<string> logger )
      : base( childEnumerator )
    {
      string className = this.ChildEnumerator.GetType().Name;

      if( className.StartsWith( "SyncDebugLogEnumerator", StringComparison.Ordinal ) )
      {
        logger = null;
      }

      m_debugLogManager = new DebugLogManager( className, logger );
    }

    protected DebugLogManager LogManager
    {
      get
      {
        return m_debugLogManager;
      }
    }

    protected override void ChildDataChanged( object sender, DataChangedEventArgs e )
    {
      string replacedItems = "(null)";
      if( e.LoadedItems != null )
      {
        replacedItems = "";
        foreach( Tuple<object, object> replacment in e.LoadedItems )
        {
          replacedItems += "(" + replacment.Item1 + "," + replacment.Item2 + ")";
        }
      }
      this.LogManager.LogBefore( string.Format( "DataChanged_event(Action={0}, NewItem={1}, OldItem={2}, RemovePosition={3}, NewCurrentPosition={4}, UpdateItems={5}, LoadedItems={6})", e.Action, e.NewItem, e.OldItem, e.RemovePosition, e.NewCurrentPosition, e.UpdateItems, replacedItems ) );
      base.ChildDataChanged( sender, e );
      this.LogManager.LogAfter( string.Format( "DataChanged_event (Handling unknown) (Action={0}, NewItem={1}, OldItem={2}, RemovePosition={3}, NewCurrentPosition={4}, UpdateItems={5}, LoadedItems={6})", e.Action, e.NewItem, e.OldItem, e.RemovePosition, e.NewCurrentPosition, e.UpdateItems, replacedItems ) );
    }

    protected string FormatFetchedItems( ICollection fetchedObjects )
    {
      if( fetchedObjects == null )
        return "Fetch=(null)";

      if( fetchedObjects.Count != 1 )
        return "FetchCount=" + fetchedObjects.Count;

      return string.Format( "Fetch={0}", fetchedObjects.Cast<object>().First() );
    }

    #region ISyncEnumerator<T> Members

    public override bool JumpMoveAndFetch(
      JumpMoveAndFetchParameters parameters,
      out Nullable<long> actualMoveCount, 
      out ICollection<T> fetchedItems, 
      out SourcePosition endPosition,
      out RelativeOffset endPositionOffset,
      out EstimateInt64 totalCount )
    {
      this.LogManager.LogBefore( 
        "JumpMoveAndFetch",
        parameters.SourcePosition,
        parameters.ExpectedMoveCount,
        parameters.ExpectedFetchCount );

      bool ret = base.JumpMoveAndFetch(
                   parameters,
                   out actualMoveCount,
                   out fetchedItems,
                   out endPosition,
                   out endPositionOffset,
                   out totalCount );

      this.LogManager.LogR(
        "JumpMoveAndFetch",
        ret,
        actualMoveCount,
        FormatFetchedItems( DataUtils.ConvertToNonGeneric<T>( fetchedItems ) ),
        endPosition );

      return ret;
    }

    #endregion ISyncEnumerator<T> Members

    #region ISyncEnumerator Members

    public override CountResult Count( CountParameters parameters )
    {
      this.LogManager.LogBefore(
        "Count",
        parameters );

      CountResult countResult = base.Count( parameters );

      this.LogManager.LogR(
              "Count",
              countResult,
              parameters );

      return countResult;
    }

    public override GroupCountResult GroupCount( CountParameters parameters )
    {
      this.LogManager.LogBefore(
        "GroupCount",
        parameters );

      GroupCountResult groupCount = base.GroupCount( parameters );

      this.LogManager.LogR(
              "GroupCount",
              groupCount,
              parameters );

      return groupCount;
    }

    public override StatResults GetStatValues( StatParameters parameters )
    {
      this.LogManager.LogBefore(
        "GetStatValue",
        parameters.StatFunctions,
        parameters.TargetPath );

      StatResults statResult = base.GetStatValues( parameters );

      this.LogManager.LogR(
              "GetStatValue",
              statResult,
              parameters.StatFunctions,
              parameters.TargetPath );

      return statResult;
    }

    public override bool JumpMoveAndFetch(
      JumpMoveAndFetchParameters parameters,
      out Nullable<long> actualMoveCount, 
      out ICollection fetchedItems, 
      out SourcePosition endPosition,
      out RelativeOffset endPositionOffset,
      out EstimateInt64 totalCount )
    {
      this.LogManager.LogBefore( 
        "JumpMoveAndFetch",
        parameters.SourcePosition,
        parameters.ExpectedMoveCount,
        parameters.ExpectedFetchCount );

      bool ret = base.JumpMoveAndFetch(
                   parameters,
                   out actualMoveCount,
                   out fetchedItems,
                   out endPosition,
                   out endPositionOffset,
                   out totalCount );

      this.LogManager.LogR(
        "JumpMoveAndFetch",
        ret,
        actualMoveCount,
        FormatFetchedItems( fetchedItems ),
        endPosition );

      return ret;
    }

    #endregion ISyncEnumerator Members

    private DebugLogManager m_debugLogManager;
  }
}
